/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package forcadistribuido;

import forcadistribuido.remoteServerInterface.IForcaRemota;
import forcadistribuido.remoteClientInterface.IRemoteClient;
import java.rmi.RemoteException;
import java.util.Hashtable;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author matheus
 * 
 */
public class ForcaRemota implements IForcaRemota{

    private Vector<IRemoteClient> jogadoresRegistrados;

    private Vector<IRemoteClient> jogadoresQJogam;

    private Hashtable<String,Integer> erros;

    private String palavra = "PALAVRA";

    String[] listaPalavras = {"PETROLEO", "PESTANA", "PESTILENTO", "PETELECO", "REBOQUE", "CADAFALSO",
        "CADEIRA", "COLA", "REBENTO", "DEFUMADO", "DISCURSO", "ELETRODOMESTICO",
        "ELETRONICA", "ENGRENAGEM", "ESFOMEADO", "FERRALHEIRO", "FERROVIA",
        "FERTIL", "FORTALEZA", "FORTIFICANTE", "OFICINA", "ORNAMENTO", "PALAVRA",
        "PREOCUPACAO", "RADIOLOGIA", "RADIOGRAFIA", "GRANJA", "GRANULADO", "INDUZIDO",
        "IMBATIVEL", "INDUSTRIA", "INTERNACIONAL", "LABIRINTO", "LOBISOMEM",
        "LOCOMOTIVA", "TESOURA", "MASSAGISTA", "MATADOURO", "MOCHILA", "NOROESTE",
        "NITROGLICERINA", "HELICOPTERO", "CAPITALISMO", "SOFTWARE", "ENGENHARIA",
        "NOROESTE", "AUTENTICO", "LINUX", "PROCESSADOR", "QUARENTENA", "MEDICINA",
        "HOLOCAUSTO", "RADIOGRAFIA", "XAROPE", "ZAROLHO", "ZOOLOGICO", "HEREDITARIO",
        "EXTASE", "EXTRAVIO", "DUODENO", "ECOLOGISTA", "TURISMO", "TRAFICANTE",
        "CONSELHO", "BAIXISTA", "AVESTRUZ", "QUIMICA", "BOTANICA", "RESPECTIVO",
        "SAXOFONE", "TABERNA", "OCULTO", "TRIGONOMETRIA", "ZODIACO", "JUSTAPOSTO",
        "HIDRAULICO", "HEXAGONO", "MINEIRO", "FRENETICO", "EXPLOSIVO", "EXORCISTA"};

    private String[] palavra_mascara;

    private int indexVez;

    private final int NONE = -1;

    private int RESTART_TIME;

    private boolean fimDeJogo = false;

    public ForcaRemota() {
        jogadoresRegistrados = new Vector<IRemoteClient>();
        erros = new Hashtable<String,Integer>();
        jogadoresQJogam = new Vector<IRemoteClient>();

        palavra = sorteiaPalavra();
        
        palavra_mascara = new String[palavra.length()];
        for(byte i = 0; i < palavra_mascara.length;i++){
            palavra_mascara[i] = "_ ";
        }
        indexVez = NONE;
    }

    
    public boolean jogar(IRemoteClient jogador) throws RemoteException {
        for (IRemoteClient i : jogadoresRegistrados) {
            if (i.getNomeJogador().equalsIgnoreCase(jogador.getNomeJogador())) {
                System.out.println("O jogador " + jogador.getNomeJogador() + " já " +
                        "está cadastrado");
                return false;
            }
        }

        jogadoresRegistrados.add(jogador);
        jogadoresQJogam.add(jogador);
        erros.put(jogador.getNomeJogador(), 0);
        
        System.out.println("O jogador " + jogador.getNomeJogador() + " está no jogo");

        if(jogadoresQJogam.size() == 1)
            indexVez = jogadoresQJogam.indexOf(jogadoresQJogam.firstElement());
        
        System.out.println("index de "+jogador.getNomeJogador()+" : "+jogadoresRegistrados.indexOf(jogador));
        return true;
    }

    
    public boolean sair(IRemoteClient jogador) throws RemoteException {
        for (IRemoteClient i : jogadoresRegistrados) {
            if (i.getNomeJogador().equalsIgnoreCase(jogador.getNomeJogador())) {
                jogadoresRegistrados.remove(jogador);
                jogadoresQJogam.remove(jogador);
                erros.remove(jogador.getNomeJogador());
                System.out.println("O jogador " + jogador.getNomeJogador() + " está fora do jogo");

                if(jogadoresQJogam.isEmpty())
                    indexVez = NONE;
                return true;
            }
        }

        System.out.println("O jogador " + jogador.getNomeJogador() + " não está cadastrado");
        return false;
    }

    /**
     * Notifica os jogadoresRegistrados do palpite acertado de um jogador
     */
    public void notificaPalpite(IRemoteClient jogador){
        for(IRemoteClient i: jogadoresQJogam){
            try {
                i.atualizaPalavra(palavraSecreta());
            } catch (RemoteException ex) {
                Logger.getLogger(ForcaRemota.class.getName()).log(Level.SEVERE, null, ex);
            }
        }        
    }

    public int tamanhoPalavra() throws RemoteException {
        return palavra.length();
    }

    private void reiniciar(IRemoteClient vencedor, int indexVencedor) {
        for (IRemoteClient r : jogadoresRegistrados) {
            try {
                r.atualizaStatusJogo2("Reiniciando...");
            }catch (RemoteException ex) {
                Logger.getLogger(ForcaRemota.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        try {
            Thread.sleep(1000 * 2);
            jogadoresQJogam.clear();
            for (IRemoteClient i : jogadoresRegistrados) {
                jogadoresQJogam.add(i);
                erros.put(i.getNomeJogador(), 0);
            }

            palavra = sorteiaPalavra();

            palavra_mascara = new String[palavra.length()];
            for (byte i = 0; i < palavra_mascara.length; i++) {
                palavra_mascara[i] = "_ ";
            }
            indexVez = (int) (Math.random() * jogadoresQJogam.size());            
            
            for (IRemoteClient i : jogadoresRegistrados) {
                i.atualizaForca(0);
                i.atualizaPalavra(palavraSecreta());
                i.atualizaStatusJogo2("Jogo reiniciado!");
            }

            notificaVez(jogadoresQJogam.get(indexVez));

            fimDeJogo = false;
            
        } catch (RemoteException ex) {
            Logger.getLogger(ForcaRemota.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InterruptedException ex) {
            Logger.getLogger(ForcaRemota.class.getName()).log(Level.SEVERE, null, ex);
        }


    }

    public boolean enviarPalpite(String c, IRemoteClient jogador) throws RemoteException {
        if (!fimDeJogo) {
            if (palavra.contains(c) && !jaEscolhida(c)) {

                for (byte i = 0; i < palavra.length(); i++) {
                    if (String.valueOf(palavra.charAt(i)).equalsIgnoreCase(c)) {
                        palavra_mascara[i] = c;
                    }
                }

                notificaJogada(jogador, c);
                notificaPalpite(jogador);
                                
                if (fimDejogo()) {
                    notificaFimDeJogo(jogador);
                    try {
                        Thread.sleep(3 * 1000);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(ForcaRemota.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    reiniciar(jogador,indexVez);
                }
                passaVez();
                return true;

            }

            notificaJogada(jogador, c);
            notificaPalpite(jogador);
            if(notificaForca(jogador)){
                passaVez();
            }
            
            return false;
        }

        return false;

    }

    private String sorteiaPalavra() {
        int indicePalavra;
        String palavraSorteada;

        // Sorteia indice da palavra
        indicePalavra = (int) (Math.random() * listaPalavras.length);

        // Seleciona a palavra correspondente ao indice sorteado no array de palavras
        palavraSorteada = listaPalavras[indicePalavra];

        System.out.println(palavraSorteada);

        // Retorna palavra sorteada
        return palavraSorteada;
    }

    private boolean jaEscolhida(String c){
        for(int i = 0; i < palavra_mascara.length; i++){
            if(palavra_mascara[i].equalsIgnoreCase(c)){
                return true;
            }
        }
        return false;
    }

    private void passaVez(){
        if(indexVez == jogadoresQJogam.lastIndexOf(jogadoresQJogam.lastElement())){
            indexVez = jogadoresQJogam.lastIndexOf(jogadoresQJogam.firstElement());
            notificaVez(jogadoresQJogam.firstElement());
        }else{
            indexVez++;
            notificaVez(jogadoresQJogam.get(indexVez));
        }
    }

    public boolean verificaVez(IRemoteClient jogador){
        if(indexVez == jogadoresQJogam.indexOf(jogador)){
            return true;
        }else{
            return false;
        }
    }

    public String palavraSecreta() throws RemoteException {
        String word = "";
        for(String i: palavra_mascara){
            word = word.concat(i);
        }
        word = word.trim();
        return word;
    }

    private boolean fimDejogo(){
        for(byte i = 0; i < palavra_mascara.length; i++){
            if(palavra_mascara[i].equalsIgnoreCase("_ ")){
                return false;
            }
        }
        //JOptionPane.showMessageDialog(null, "O jogo terminou","Fim de jogo", JOptionPane.INFORMATION_MESSAGE);

        fimDeJogo = true;
        return true;
    }

    private boolean notificaForca(IRemoteClient jogador){
        try {
            int qtdErros = erros.get(jogador.getNomeJogador());
            qtdErros++;
            jogador.atualizaForca(qtdErros);
            jogador.atualizaStatusJogo("Essa letra não consta na palavra secreta");
            if(qtdErros == 6){
                //jogadoresRegistrados.remove(jogador);
                jogadoresQJogam.remove(jogador);
                erros.put(jogador.getNomeJogador(), 0);
                jogador.atualizaStatusJogo("FORCA! Você perdeu e foi eliminado do jogo.");
                notificaVez(jogadoresQJogam.get(indexVez));
                return false;
            }else{
                erros.put(jogador.getNomeJogador(), qtdErros);
            }

        } catch (RemoteException ex) {
            Logger.getLogger(ForcaRemota.class.getName()).log(Level.SEVERE, null, ex);
        }

        return true;
    }

    private void notificaFimDeJogo(IRemoteClient jogador){
        //try {
            for (IRemoteClient i : jogadoresRegistrados) {
                try {
                    if (i.getNomeJogador().equalsIgnoreCase(jogador.getNomeJogador())) {
                        i.atualizaStatusJogo("Você ganhou!");
                    } else {
                        i.atualizaStatusJogo(jogador.getNomeJogador() + " ganhou!");
                    }
                } catch (RemoteException ex) {
                    Logger.getLogger(ForcaRemota.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
//            Thread.sleep(2 * 1000);
//        } catch (InterruptedException ex) {
//            Logger.getLogger(ForcaRemota.class.getName()).log(Level.SEVERE, null, ex);
//        }
    }

    private void notificaJogada(IRemoteClient jogador, String c){
        for(IRemoteClient i: jogadoresRegistrados){
            try {
                if(i.getNomeJogador().equalsIgnoreCase(jogador.getNomeJogador())){
                    i.atualizaStatusJogo2("Você jogou "+ "'"+c+"'");
                }else{
                    i.atualizaStatusJogo2(jogador.getNomeJogador() + " jogou "+"'"+c+"'");
                }

            } catch (RemoteException ex) {
                Logger.getLogger(ForcaRemota.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    private void notificaVez(IRemoteClient jogador){
        for(IRemoteClient i: jogadoresQJogam){
            try {
                if(i.getNomeJogador().equalsIgnoreCase(jogador.getNomeJogador())){
                    i.atualizaStatusJogo("Sua vez!");
                }else{
                    i.atualizaStatusJogo(jogador.getNomeJogador() + " é quem joga.");
                }

            } catch (RemoteException ex) {
                Logger.getLogger(ForcaRemota.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    public String statusVez(IRemoteClient jogador) throws RemoteException {
        if(jogador.getNomeJogador().equalsIgnoreCase(jogadoresQJogam.get(indexVez).getNomeJogador())){
            return "É você quem joga.";
        }
        return jogadoresQJogam.get(indexVez).getNomeJogador() + " é quem joga!";
    }

}
